package com.lions.client.view.modulepanel;

import com.google.gwt.dom.client.Style.Unit;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.ListBox;
import com.google.gwt.user.client.ui.StackLayoutPanel;
import com.lions.client.controller.Controller;
import com.lions.client.model.Condition;
import com.lions.client.model.Model;
import com.lions.client.model.Module;
import com.lions.client.model.Type;
import com.lions.client.view.audio.AudioOutput;
import com.lions.client.view.basepanel.BasePanel;
import com.lions.client.view.mappanel.MapPanel;
import com.lions.client.view.mappanel.SandboxMapPanel;
import com.lions.client.view.popup.MyPopupPanel;

// TODO: Auto-generated Javadoc
/**
 * This class builds the GUI that represents the module list. It displays the
 * list and controls the addition of modules by MyPopup.
 * 
 * @author Kyle Fink
 */
public class ModulePanel extends StackLayoutPanel {

	/**
	 * Constructor creates the GUI and all of its stacks, also obtains the data
	 * from a previous session.
	 * 
	 * @param m
	 *            Model holding the data
	 * @param c
	 *            Controller holding the logic
	 * @param map
	 *            MapPanel holding the GUI locations of modules
	 * @param sandMap
	 *            the sand map
	 * @param base
	 *            the base
	 */
	public ModulePanel(final Model m, final Controller c, final MapPanel map,
			final SandboxMapPanel sandMap, final BasePanel base) {
		super(Unit.EM);
		model = m;
		controller = c;
		panel = this;
		mapPanel = map;
		sandboxPanel = sandMap;
		basePanel = base;
		setSize("100%", "100%");
		setStyleName("splitlayoutstyle");

		// Creates listeners for buttons
		createClickHandlers();

		// Creates the stacks within this stack layout panel
		updateStackTitles();

	}

	/**
	 * This initializes the stacks within the layout panel.
	 */
	public void updateStackTitles() {

		add(air, new HTML("[Airlock]" + " [ " + air.getItemCount() + " ]"),
				tabSize);
		add(canteen, new HTML("[Canteen]" + " [ " + canteen.getItemCount()
				+ " ]"), tabSize);
		add(control, new HTML("[Control]" + " [ " + control.getItemCount()
				+ " ]"), tabSize);
		add(dorm, new HTML("[Dormitory]" + " [ " + dorm.getItemCount() + " ]"),
				tabSize);
		add(foodNwater,
				new HTML("[Food & Water]" + " [ " + foodNwater.getItemCount()
						+ " ]"), tabSize);
		add(gymNrelax,
				new HTML("[Gym & Relaxation]" + " [ "
						+ gymNrelax.getItemCount() + " ]"), tabSize);
		add(medical, new HTML("[Medical]" + " [ " + medical.getItemCount()
				+ " ]"), tabSize);
		add(plain, new HTML("[Plain]" + " [ " + plain.getItemCount() + " ]"),
				tabSize);
		add(power, new HTML("[Power]" + " [ " + power.getItemCount() + " ]"),
				tabSize);
		add(sanitation,
				new HTML("[Sanitation]" + " [ " + sanitation.getItemCount()
						+ " ]"), tabSize);
	}

	/**
	 * Takes a single module and adds it to its respective list. This method has
	 * a private helper method.
	 * 
	 * @param mod
	 *            Module to add to the list
	 */
	public void addModule(final Module mod) {
		model.addModule(mod);
		populate();
	}

	/**
	 * Takes a single module and adds it to its respective list. This method has
	 * a private helper method.
	 * 
	 * @param oldMod
	 *            the old mod
	 * @param newMod
	 *            the new mod
	 */
	public void editModule(final Module oldMod, final Module newMod) {
		model.editModule(oldMod, newMod);
		populate();
	}

	/**
	 * Removes the module.
	 * 
	 * @param x
	 *            the x
	 * @param y
	 *            the y
	 */
	public void removeModule(final int x, final int y) {
		model.removeModuleAtCoord(x, y);
		populate();
	}

	/**
	 * Updates the moduleList and the mapPanel.
	 */
	public void populate() {
		mapPanel.populate();
		sandboxPanel.populate();
		basePanel.populate();
		clearAllPanels();
		for (Module mod : model.getModuleList()) {
			if (mod == null) {
			} else {
				if (mod.getType() == Type.AIRLOCK) {
					addToSpecifiedStack(air, mod, air.getItemCount());
					if (mod.getCondition() == Condition.USABLE) {
						air.addStyleName("usable");
					} else if (mod.getCondition() == Condition.REPAIRABLE) {

						air.addStyleName("repair");
					} else {
						air.addStyleName("broken");
					}
				} else if (mod.getType() == Type.POWER) {
					addToSpecifiedStack(power, mod, power.getItemCount());

				} else if (mod.getType() == Type.PLAIN) {
					addToSpecifiedStack(plain, mod, plain.getItemCount());

				} else if (mod.getType() == Type.SANITATION) {
					addToSpecifiedStack(sanitation, mod,
							sanitation.getItemCount());

				} else if (mod.getType() == Type.CANTEEN) {
					addToSpecifiedStack(canteen, mod, canteen.getItemCount());

				} else if (mod.getType() == Type.FOOD_WATER_STORAGE) {
					addToSpecifiedStack(foodNwater, mod,
							foodNwater.getItemCount());

				} else if (mod.getType() == Type.GYM) {
					addToSpecifiedStack(gymNrelax, mod,
							gymNrelax.getItemCount());

				} else if (mod.getType() == Type.CONTROL) {
					addToSpecifiedStack(control, mod, control.getItemCount());

				} else if (mod.getType() == Type.MEDICAL) {
					addToSpecifiedStack(medical, mod, medical.getItemCount());

				} else if (mod.getType() == Type.DORMITORY) {
					addToSpecifiedStack(dorm, mod, dorm.getItemCount());

				}

			}
			this.updateStackTitles();
		}
	}

	/**
	 * Utility method for the listAddSingle method.
	 * 
	 * @param ls
	 *            the ls
	 * @param mod
	 *            the mod
	 * @param itemCount
	 *            the item count
	 */
	private void addToSpecifiedStack(final ListBox ls, final Module mod,
			final int itemCount) {
		int xcord = mod.getX();
		int ycord = mod.getY();

		String display = "Xcord: " + String.valueOf(xcord) + " " + "Ycord: "
				+ String.valueOf(ycord);
		ls.addItem(display);
		ls.setVisibleItemCount(itemCount + 2);
	}

	/**
	 * Creates all of the click handlers associated with this panel. These click
	 * handlers will come from the Controller panel which actually has the
	 * buttons.
	 */
	private void createClickHandlers() {
		// Add module add button click handler
		controller.getAddButton().addClickHandler(new ClickHandler() {
			@Override
			public void onClick(final ClickEvent event) {
				ModulePopup popup = new ModulePopup(panel, mapPanel);
				popup.center();
				popup = null;
			}
		});

		// Add delete module button click handler
		controller.getModuleRemoveButton().addClickHandler(new ClickHandler() {
			@Override
			public void onClick(final ClickEvent event) {
				ListBox visible = getVisibleListBox();
				if (visible != null) {
					int modIndex = visible.getSelectedIndex();
					if (modIndex >= 0) {
						String modString = visible.getItemText(modIndex);
						// ## Ycord: ##
						modString = modString.substring(modString.indexOf(':') + 2);
						int xCoord = Integer.parseInt(modString.substring(ZERO,
								modString.indexOf(" ")));
						// ##
						modString = modString.substring(modString.indexOf(':') + 2);
						int yCoord = Integer.parseInt(modString);
						// Delete module
						removeModule(xCoord, yCoord);
					} else {
						new MyPopupPanel("Select Module",
								"Please Select a Module.");
						new AudioOutput().playInputError();
					}
				} else {
					new MyPopupPanel("Select Module", "Please Select a Module.");
					new AudioOutput().playInputError();
				}
			}
		});

		// Add edit module button click handler
		controller.getEditButton().addClickHandler(new ClickHandler() {
			@Override
			public void onClick(final ClickEvent event) {
				ListBox visible = getVisibleListBox();
				if (visible != null) {
					int modIndex = visible.getSelectedIndex();
					if (modIndex >= 0) {
						String modString = visible.getItemText(modIndex);
						// ## Ycord: ##
						modString = modString.substring(modString.indexOf(':') + 2);
						int xCoord = Integer.parseInt(modString.substring(ZERO,
								modString.indexOf(" ")));
						// ##
						modString = modString.substring(modString.indexOf(':') + 2);
						int yCoord = Integer.parseInt(modString);
						// Edit Module
						if (model.getModuleList().getModuleAtCoord(xCoord,
								yCoord) != null) {
							Module mod = model.getModuleList()
									.getModuleAtCoord(xCoord, yCoord);
							EditModulePopup popup = new EditModulePopup(panel,
									mapPanel, mod);
							popup.center();
							popup = null;
						} else {
							new MyPopupPanel("Error",
									"Error: Could Not Find Module");
							new AudioOutput().playBaseError();
						}
						// Redraw modList and mapPanel
					} else {
						new MyPopupPanel("Select Module",
								"Please Select a Module.");
						new AudioOutput().playInputError();
					}
				} else {
					new MyPopupPanel("Select Module", "Please Select a Module.");
					new AudioOutput().playInputError();
				}
			}
		});
	}

	/**
	 * Accessor for the model passed to this class during construction.
	 * 
	 * @return Pointer to model
	 */
	public Model getModel() {
		return model;
	}

	/**
	 * Clear all panels.
	 */
	public void clearAllPanels() {
		air.clear();
		power.clear();
		plain.clear();
		sanitation.clear();
		canteen.clear();
		foodNwater.clear();
		gymNrelax.clear();
		control.clear();
		medical.clear();
		dorm.clear();
		this.updateStackTitles();
		mapPanel.populate();
	}

	/**
	 * Gets the visible list box.
	 * 
	 * @return the visible list box
	 */
	public ListBox getVisibleListBox() {
		ListBox visible = null;
		if (getVisibleIndex() == 0) {
			visible = air;
		} else if (getVisibleIndex() == 1) {
			visible = canteen;
		} else if (getVisibleIndex() == 2) {
			visible = control;
		} else if (getVisibleIndex() == 3) {
			visible = dorm;
		} else if (getVisibleIndex() == 4) {
			visible = foodNwater;
		} else if (getVisibleIndex() == 5) {
			visible = gymNrelax;
		} else if (getVisibleIndex() == 6) {
			visible = medical;
		} else if (getVisibleIndex() == 7) {
			visible = plain;
		} else if (getVisibleIndex() == 8) {
			visible = power;
		} else if (getVisibleIndex() == 9) {
			visible = sanitation;
		}
		return visible;
	}

	// Public Local Variables
	/** The panel. */
	public ModulePanel panel;
	// Private Local Variables
	/** The tab size. */
	private int tabSize = 2;

	/** The zero. */
	private int ZERO = 0;

	/** The model. */
	public Model model;

	/** The controller. */
	private Controller controller;

	/** The map panel. */
	private MapPanel mapPanel;

	/** The sandbox panel. */
	private SandboxMapPanel sandboxPanel;

	/** The base panel. */
	private BasePanel basePanel;

	/** The air. */
	private ListBox air = new ListBox();

	/** The power. */
	private ListBox power = new ListBox();

	/** The plain. */
	private ListBox plain = new ListBox();

	/** The sanitation. */
	private ListBox sanitation = new ListBox();

	/** The canteen. */
	private ListBox canteen = new ListBox();

	/** The food nwater. */
	private ListBox foodNwater = new ListBox();

	/** The gym nrelax. */
	private ListBox gymNrelax = new ListBox();

	/** The control. */
	private ListBox control = new ListBox();

	/** The medical. */
	private ListBox medical = new ListBox();

	/** The dorm. */
	private ListBox dorm = new ListBox();

}
